package com.producer.config;

import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@Component
public class RabbitAdminConfig {
    /**
     * 一个exchange可以绑定多gueue，一个queue也可以绑定到多个exchange上。
     */
    @Bean("rabbitAdmin")
    public RabbitAdmin rabbitAdmin(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);

		/*
		  交换机Exchange
		  如果发送给交换机的消息没有任何路由规则匹配，则会被丢弃
		  	1.类型type：
		  		扇形交换机fanout Exchange
		  			又称广播交换机，交换机收到消息后就会传给所有与它绑定的队列
		  		直连交换机direct Exchange
		  			队列Queue与之绑定时需要声明绑定的routingKey，往交换机发送消息时也需要指定routingKey，只有发送消息时指定的routingKey与绑定时的完全一致的队列Queue才会收到消息
		  		主题队列topic Exchange
		  			和直连交换机类型，绑定时的routingKey可以是表达式，发送消息时指定的routingKey如果匹配绑定时的，则就可以发送到相应的队列
		  			表达式的模糊匹配符号主要是#和*，#匹配一个或者多个词组，词组是指以点.分割的单词，比如user.#  # 可以匹配到 user.add  user.add.batch
		  			*只能匹配一个词组，例如user.* 只能匹配到 user.add ，不能匹配到 user.add.batch
		  		headers Exchange
		  			发送消息时，可以指定消息的头部参数，效率比较低，不常用
		  	2.Durability：Durable或者Transient 持久化标识，如果为Durable，则表明此exchange为持久化的，否则只是临时的，交换机重启后消息就没有了
		  	3.Auto delete：当最后一个绑定到exchange上的队列删除后，自定删除该exchange
		  	4.Internal：当前exchange是否用于rabbitmq内部使用，默认为false
		 */
        //这里只是声明交换机，不存在也不会报错，也不会创建
        /*
        DirectExchange firstDirectExchange = new DirectExchange("first.exchange.direct",false,false);
        //如果交换机不存在会创建
        rabbitAdmin.declareExchange(firstDirectExchange);

        Map<String, Object> arguments = new HashMap<String, Object>();
        arguments.put("x-dead-letter-exchange", "firstdead.exchange.direct");
        arguments.put("x-dead-letter-routing-key", "first.dead.routingkey");
        DirectExchange deadDirectExchange = new DirectExchange("firstdead.exchange.direct",false,false,arguments);
        rabbitAdmin.declareExchange(deadDirectExchange);
        */
		/*
		  队列Queue
		  	1：类型
		  		Classic：主队列
		  		Quorum：从队列
		   2.durability：queue中的消息是否持久化到硬盘
		   3.auto delete：如果此queue没有绑定到任何一个exchange，是否自动删除此queue
		 */
        //这里只是声明队列，不存在也不会报错，也不会创建
        /*
        Queue firstQueue = new Queue("first.queue",false,false,false);
        //如果队列不存在会创建
        rabbitAdmin.declareQueue(firstQueue);
        rabbitAdmin.declareBinding(BindingBuilder.bind(firstQueue).to(firstDirectExchange).with("first.routingkey"));

        Queue deadQueue = new Queue("firstdead.queue",false,false,false);
        rabbitAdmin.declareQueue(deadQueue);
        rabbitAdmin.declareBinding(BindingBuilder.bind(deadQueue).to(deadDirectExchange).with("firstdead.exchange.direct"));


        Queue secondQueue = new Queue("second.queue",false,false,false);
        //如果队列不存在会创建
        rabbitAdmin.declareQueue(secondQueue);
        rabbitAdmin.declareBinding(BindingBuilder.bind(secondQueue).to(firstDirectExchange).with("first.routingkey"));
        */

		/*
		延迟队列 TTL（time to live），SpringBoot中设置的单位为毫秒
		过期时间TTL表示可以对消息设置预期的时间，在这个时间内都可以被消费者消费，超过了则会被删除或者进入死信队列等
		延迟时间可以通过两种方式设置
		1：通过队列属性设置，队列中的消息都具有相同的TTL
		2：通过对消息进行单独设置，每条消息的TTL可以不同
		如果同时指定了队列和消息的TTL，则两者中较小的那个才会起作用

		一般进入死信队列的原因：
		1.消息被消费者reject或者返回nack，并且requeue设置为false
		2.消息过期
		3.队列达到最大长度
		*/

        return rabbitAdmin;
    }
}
